#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Create by zhang
# Create on 2022/6/29 18:27
import re
from enum import IntEnum
from typing import List
from time import strptime

from domain.report.common.currency_type import CurrencyTypeEnum
from domain.report.common.money_unit import MoneyUnitEnum
from domain.report.common.task_status import TaskStatusEnum
from domain.report.common.extract_content_enum import ExtractContentEnum
from domain.report.extractor.request import TaskData, Request
from infrastructure.filter.filter import FilterInterface


class FilterItemTypeEnum(IntEnum):
    NON_EQUATION = 0
    EQUATION = 1
    STARTWITH = 2


class BaseFilter(FilterInterface):
    start_titles = []
    item_titles = []
    end_titles = []
    replace_start = ["减：", "加：", "其中：",
                     "一、", "二、", "三、", "四、", "五、", "六、", "七、", "八、", "九、",
                     "（一）", "（二）", "（三）", "（四）", "（五）", "（六）", "（七）", "（八）", "（九）",
                     "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9."]
    replace_end = ["（损失以“－”号填列）", "（亏损以“－”号填列）", "（亏损总额以“－”号填列）", "（净亏损以“－”号填列）"]

    def __init__(self):
        super(BaseFilter, self).__init__()
        self.extract_type:ExtractContentEnum = None
        self.exclude_type:List[ExtractContentEnum] = list
        self.result:TaskData = None
        self.init()

    def init(self):
        raise Exception('子类中必须实现该方法')

    def filter(self, request:Request) -> None:
        p = request.current_page()
        text = p.extract_text(layout=True)
        if self.check(text):
            if request.get_data(self.result) is None or len(request.get_data(self.result).data) == 0:
                request.add_data(self.result)
            self.result:TaskData = request.get_data(self.result)
            self.result.status = TaskStatusEnum.START
            tables = p.extract_tables()
            lines = text.split("\n")
            for l in lines:
                if l is None or len(l) == 0:
                    continue
                if CurrencyTypeEnum.RMB.title in l:
                    self.result.set("currency", CurrencyTypeEnum.RMB)
                elif CurrencyTypeEnum.DOLLAR.title in l:
                    self.result.set("currency", CurrencyTypeEnum.DOLLAR)

                if MoneyUnitEnum.THOUSAND.title in l:
                    self.result.set("money_unit", MoneyUnitEnum.THOUSAND)
                elif MoneyUnitEnum.TEN_THOUSAND.title in l:
                    self.result.set("money_unit", MoneyUnitEnum.TEN_THOUSAND)
                elif MoneyUnitEnum.HUNDRED_THOUSAND.title in l:
                    self.result.set("money_unit", MoneyUnitEnum.HUNDRED_THOUSAND)
                elif MoneyUnitEnum.MILLION.title in l:
                    self.result.set("money_unit", MoneyUnitEnum.MILLION)
                elif MoneyUnitEnum.ONE.title in l:
                    self.result.set("money_unit", MoneyUnitEnum.ONE)

                if tables is None or len(tables) == 0:
                    self.filter_fill_item(self.remove_empty_item(re.split(r"\s+", l)))
                elif self.result.get("currency") is not None and self.result.get("money_unit") is not None:
                    break
            for table in tables:
                if self.result.status == TaskStatusEnum.START:
                    for row in table:
                        self.filter_fill_item([item if item is not None else "" for item in row])


    def check(self, check_item:str) -> bool:
        if self.result.status == TaskStatusEnum.START:
            return True
        if self.extract_type.title in check_item:
            for item in self.exclude_type:
                if item.title in check_item:
                    return False
            for start_ in self.__class__.start_titles:
                if start_ not in check_item:
                    return False
            return True
        return False

    def remove_empty_item(self, items:list):
        datas = list()
        if items and len(items) > 0:
            for item in items:
                if not item:
                    item = ""
                item = item.replace(" ", "")
                if item and len(str(item)) > 0:
                    datas.append(item)
        return datas

    def filter_fill_item(self, items:list):
        if not items or len(items) == 0:
            return items

        date_count = 0
        for i, item in enumerate(items):
            date_count = date_count+1 if self.is_date(item) else date_count
            items[i] = re.sub(r"\s", "", item)
            if self.__class__.replace_start is not None and len(self.__class__.replace_start) > 0:
                for starter in self.__class__.replace_start:
                    index = len(starter)
                    items[i] = item[index:] if item.startswith(starter) else item

            if self.__class__.replace_end is not None and len(self.__class__.replace_end) > 0:
                for end in self.__class__.replace_end:
                    index = len(end)
                    items[i] = item[index:] if item.endswith(starter) else item

        size = len(items)
        data:list = self.result.get(self.extract_type.name)
        new_title = items[0] + self.temp_item[0] if self.temp_item is not None and len(self.temp_item) > 0 else items[0]
        is_filter_item_status = self.is_fitler_item(new_title)
        if is_filter_item_status == FilterItemTypeEnum.STARTWITH:
            self.temp_item = items
        elif is_filter_item_status == FilterItemTypeEnum.EQUATION and self.temp_item is not None and len(self.temp_item) > 0:
            items = [
                new_title,
                self.temp_item[1] if len(self.temp_item) > 1 and self.temp_item[1] is not None and self.temp_item[1] != "" and (len(items) == 1 or items[1] is None or items[1] == "") else items[1],
                self.temp_item[2] if len(self.temp_item) > 2 and self.temp_item[2] is not None and self.temp_item[2] != "" and (len(items) <= 2  or items[2] is None or items[2] == "") else items[2],
                self.temp_item[3] if len(self.temp_item) > 3 and self.temp_item[3] is not None and self.temp_item[3] != "" and (len(items) <= 3  or items[3] is None or items[3] == "") else items[3]
            ]
            self.temp_item == None

        for i, item in enumerate(items):
            items[i] = re.sub(r"\s", "", item)
            if self.__class__.replace_start is not None and len(self.__class__.replace_start) > 0:
                for starter in self.__class__.replace_start:
                    index = len(starter)
                    items[i] = item[index:] if item.startswith(starter) else item

            if self.__class__.replace_end is not None and len(self.__class__.replace_end) > 0:
                for end in self.__class__.replace_end:
                    index = len(end)
                    items[i] = item[index:] if item.endswith(starter) else item

        if size >= 2 and "附注" in items[1] and data is not None and len(data) > 0:
            data[0][1] = items[1]
        elif is_filter_item_status == FilterItemTypeEnum.EQUATION and len(data) > 0:
            if size == 1:
                items = items + ["", "", ""]
                data.append(items)
            elif size == 3: # 因为报表数据为空的话会用-填充，所以不会必有2个元素的情况，并且为三个元素的时候，就只有附注列为空
                # if "-" not in items[1] and "." not in items[1] and "," not in items[1]:
                items = [items[0], "", items[1], items[2]]
                data.append(items)
            elif size == 4:
                data.append(items)
        elif date_count == 2 and len(data) == 0:
            if size == 2:
                items = ["", ""] + items
                data.append(items)
            elif size == 3:
                items = [""] + items
                data.append(items)
            elif size == 4:
                data.append(items)

        if len(data) > 0 and data[-1][0] in self.__class__.end_titles:
            self.result.status = TaskStatusEnum.FINISH

    def is_fitler_item(self, title:str) -> FilterItemTypeEnum:
        if not title or len(title.replace(" ", "")) == 0:
            return FilterItemTypeEnum.NON_EQUATION
        for item in self.__class__.item_titles:
            if title == item:
                return FilterItemTypeEnum.EQUATION
            if item.startswith(title):
                return FilterItemTypeEnum.STARTWITH
            for end_item in self.__class__.replace_end:
                if f"{item}{end_item}".endswith(title):
                    return FilterItemTypeEnum.STARTWITH
        return FilterItemTypeEnum.NON_EQUATION

    def is_date(self, date_str:str):
        pattern = ['%Y年%m月%d日', '%Y年', '%Y年度']
        for i in pattern:
            try:
                ret = strptime(date_str, i)
                return True
            except:
                continue
        return False